package route

import (
	"bytes"
	"encoding/json"
	"fmt"
	//"gitee.com/gitee-go/core"
	"gitee.com/gitee-go/core/bean/oauthBean"
	"gitee.com/gitee-go/core/model/pipeline"
	"gitee.com/gitee-go/server/comm"
	"gitee.com/gitee-go/server/engine"
	"gitee.com/gitee-go/server/service"
	"gitee.com/gitee-go/utils"
	"github.com/gin-gonic/gin"
	"github.com/sirupsen/logrus"
	"io/ioutil"
	"net/http"
	"time"
)

/**
此文件主要是各个平台(gitee)oauth回调操作,主要操作:
1. 判断回调参数,是否错误
2. 通过code调用api获取accessToken并保存到数据库
3. 通过accessToken获取用户信息(昵称,头像)并保存到数据库
4. 生成临时的code以确保前端获取jwt
5. 跳转到前端url
*/

func (cs *OAuthController) backGitee(c *gin.Context, hs, code, nm string, oapp *oauthBean.AppInfo) {
	errs := c.Query("error")
	errds := c.Query("error_description")
	if code == "" || errs != "" || errds != "" {
		//httpex.ResMsgUrl(c, "授权失败-参数错误:"+errds)
		c.Redirect(302, cs.errUrl(hs, errs))
		return
	}
	buf := &bytes.Buffer{}
	rtul := fmt.Sprintf("%s/api/login/oauth/back/%s", comm.MainCfg.ServerConf.Host, nm)
	//rtul:=sysp.WebHost+c.Request.RequestURI
	//ul:="https://gitee.com/oauth/token?grant_type=authorization_code&code={code}&client_id={client_id}&redirect_uri={redirect_uri}&client_secret={client_secret}"
	buf.WriteString(fmt.Sprintf("grant_type=authorization_code&code=%s&client_id=%s&client_secret=%s&redirect_uri=%s",
		code, oapp.ClientId, oapp.ClientSecret, rtul))
	res1, err := http.Post("https://gitee.com/oauth/token", "application/x-www-form-urlencoded", buf)
	if err != nil {
		logrus.Errorf("token from code err:%v", err)
		c.Redirect(302, cs.errUrl(hs, "errs"))
		return
	}
	defer res1.Body.Close()
	bts, err := ioutil.ReadAll(res1.Body)
	if err != nil {
		c.Redirect(302, cs.errUrl(hs, "errs"))
		return
	}
	if res1.StatusCode != 200 {
		logrus.Errorf("token from code res(%d) err:%v", res1.StatusCode, err)
		mp := utils.NewMaps(bts)
		cds := mp.GetString("error")
		if cds == "" {
			cds = "token"
		}
		c.Redirect(302, cs.errUrl(hs, cds))
		return
	}
	info := &oauthBean.TokenInfo{}
	err = json.Unmarshal(bts, info)
	if err != nil {
		c.Redirect(302, cs.errUrl(hs, "token"))
		return
	}
	if info.Error != "" || info.ErrorDescription != "" {
		//httpex.ResMsgUrl(c, "授权失败-参数错误:"+errds)
		c.Redirect(302, cs.errUrl(hs, info.Error))
		return
	}
	info.CreatedTm = time.Now()
	jsontk := string(bts)
	res2, err := http.Get(fmt.Sprintf("https://gitee.com/api/v5/user?access_token=%s", info.AccessToken))
	if err != nil {
		c.Redirect(302, cs.errUrl(hs, "user"))
		return
	}
	defer res2.Body.Close()
	bts, err = ioutil.ReadAll(res2.Body)
	if err != nil {
		c.Redirect(302, cs.errUrl(hs, "user"))
		return
	}
	if res2.StatusCode != 200 {
		logrus.Errorf("user from token res(%d) err:%v", res2.StatusCode, err)
		c.Redirect(302, cs.errUrl(hs, "user"))
		return
	}
	uinfo := &oauthBean.UserInfo{}
	err = json.Unmarshal(bts, uinfo)
	if err != nil {
		c.Redirect(302, cs.errUrl(hs, "user"))
		return
	}

	isnew := false
	var usr *pipeline.TUser
	db := comm.DBMain.GetDB()
	oid := fmt.Sprintf("%d", uinfo.Id)
	tk, ok := service.FindUserToken(nm, oid)
	if !ok {
		usr = &pipeline.TUser{}
		usr.Nick = uinfo.Name
		usr.Avatar = uinfo.AvatarUrl
		usr.CreateTime = time.Now()
		_, err = db.Insert(usr)
		if err != nil || usr.Id <= 0 {
			c.Redirect(302, cs.errUrl(hs, "errs"))
			return
		}
		tk.Uid = usr.Id
		tk.Type = nm
		tk.Openid = oid
		tk.Name = uinfo.Login
		tk.Nick = uinfo.Name
		tk.Avatar = uinfo.AvatarUrl
		tk.AccessToken = info.AccessToken
		tk.RefreshToken = info.RefreshToken
		tk.ExpiresIn = info.ExpiresIn
		tk.ExpiresTime = info.CreatedTm.Add(time.Second*time.Duration(tk.ExpiresIn) - time.Second*100)
		tk.CreateTime = time.Now()
		tk.Tokens = jsontk
		tk.Uinfos = string(bts)
		_, err = db.Insert(tk)
		if err != nil || tk.Id <= 0 {
			c.Redirect(302, cs.errUrl(hs, "errs"))
			return
		}
		isnew = true
		engine.Mgr().GetRefreshEgn().PutUid(usr.Id)
	} else {
		tk.AccessToken = info.AccessToken
		tk.RefreshToken = info.RefreshToken
		tk.ExpiresIn = info.ExpiresIn
		tk.ExpiresTime = info.CreatedTm.Add(time.Second*time.Duration(tk.ExpiresIn) - 100)
		tk.Tokens = jsontk
		tk.Uinfos = string(bts)
		db.Cols("access_token", "refresh_token", "expires_in", "expires_time", "tokens", "uinfos").
			Where("id=?", tk.Id).Update(tk) // 更新数据

		usr, ok = service.GetUserCache(tk.Uid)
		if !ok {
			c.Redirect(302, cs.errUrl(hs, "errs"))
			return
		}
	}

	codes := utils.NewXid()
	mp := utils.Map{
		"uid":   usr.Id,
		"isnew": isnew,
	}
	comm.CacheSets("oauth-code:"+codes, mp, time.Minute*2)

	rdurl := "//gitee.com"
	if hs != "" {
		rdurl = hs + "/oauth"
	}
	rdurl += "?code=" + codes
	c.Redirect(302, rdurl)
}
